package cn.lili.common.security;

import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.security.enums.AuthUserFieldEnum;
import cn.lili.common.security.enums.ObjectFieldEnum;
import cn.lili.common.security.enums.SceneEnums;
import cn.lili.common.utils.BeanUtil;

import java.util.Objects;

/**
 * 全局统一判定是否可操作某属性
 *
 * @author Chopper
 * @version v1.0
 * 2020-08-20 18:07
 */
public class OperationalJudgment<T> {


    /**
     * 默认权限判定
     * <p>
     * 使用当前用户（AUTHUSER）与判定对象（OBJECT）的场景扩展id进行判定
     *
     * @param object 判定的对象
     * @return 处理结果
     */
    public static <T> T judgment(T object) {
        return judgment(object, ObjectFieldEnum.EXTEND_ID, AuthUserFieldEnum.EXTEND_ID);
    }

    /**
     * 自定义对象（OBJECT）字段权限判定
     * <p>
     * 使用当前用户的场景扩展ID与自定义字段进行判定返回
     *
     * @param object          判定的对象
     * @param objectFieldEnum 与对象中哪个字段判定的枚举
     * @return 处理结果
     */
    public static <T> T judgment(T object, ObjectFieldEnum objectFieldEnum) {
        return judgment(object, objectFieldEnum, AuthUserFieldEnum.EXTEND_ID);
    }

    /**
     * 自定义用户（AUTHUSER）字段进行权限判定
     * <p>
     * 使用权限用户字段与对象默认场景扩展字段进行判定返回
     *
     * @param object            判定的对象
     * @param authUserFieldEnum
     * @return 处理结果
     */
    public static <T> T judgment(T object, AuthUserFieldEnum authUserFieldEnum) {
        return judgment(object, ObjectFieldEnum.EXTEND_ID, authUserFieldEnum);
    }

    /**
     * 需要判定的对象必须包含属性 memberId，storeId 代表判定的角色
     *
     * @param object            判定的对象
     * @param objectFieldEnum   与对象中哪个字段判定的枚举
     * @param authUserFieldEnum 与Authuser 中哪个字段进行对比
     * @return 处理结果
     */
    public static <T> T judgment(T object, ObjectFieldEnum objectFieldEnum, AuthUserFieldEnum authUserFieldEnum) {

        //权限判定
        AuthUser authUser = UserContext.getCurrentUser();
        assert authUser != null;
        if (authUser.getScene().equals(SceneEnums.MANAGER))
            return object;


        //判定权限是否正确
        if (Objects.equals(BeanUtil.getFieldValueByName(authUser, authUserFieldEnum.field()), BeanUtil.getFieldValueByName(object, objectFieldEnum.field()))) {
            return object;
        }

        throw new ServiceException(ResultCode.USER_AUTHORITY_ERROR);
    }

    /**
     * 需要判定的对象必须包含属性 memberId，storeId 代表判定的角色
     *
     * @param object      判定的对象
     * @param objectField 与对象中哪个字段判定的枚举
     * @param authField   与Authuser 中哪个字段进行对比
     * @return 处理结果
     */
    public static <T> T judgment(T object, String objectField, String authField) {

        //权限判定
        AuthUser authUser = UserContext.getCurrentUser();
        assert authUser != null;
        if (authUser.getScene().equals(SceneEnums.MANAGER))
            return object;


        //判定权限是否正确
        if (BeanUtil.getFieldValueByName(authUser, authField)
                .equals(BeanUtil.getFieldValueByName(object, objectField))) {
            return object;
        }

        throw new ServiceException(ResultCode.USER_AUTHORITY_ERROR);
    }

    public OperationalJudgment() {
        throw new IllegalStateException("Utility class");
    }
}
